package vendas.web.action;

import gminet.infra.business.BusinessException;
import gminet.infra.db.TransactionException;
import gminet.infra.web.WebException;

import java.util.ArrayList;
import java.util.List;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.model.ListDataModel;
import javax.faces.model.SelectItem;

import org.primefaces.event.SelectEvent;
import org.primefaces.model.SelectableDataModel;

import vendas.business.OrderBusiness;
import vendas.business.OrderStatusBusiness;
import vendas.business.PaymentStatusBusiness;
import vendas.business.ProductBusiness;
import vendas.business.SellStatusBusiness;
import vendas.business.SellerBusiness;
import vendas.dao.OrderFilter;
import vendas.dto.ActionType;
import vendas.dto.CurrencyType;
import vendas.dto.Order;
import vendas.dto.OrderStatus;
import vendas.dto.PaymentStatus;
import vendas.dto.Product;
import vendas.dto.SellStatus;
import vendas.dto.Seller;

@ManagedBean(name = "orderAction")
@ViewScoped
public class OrderAction extends WebAction {

    private static final long serialVersionUID = 7370936958125882249L;

    private Order order;

    private Order selectedOrder;

    private OrderFilter orderFilter;

    private boolean pendentOrders = true;

    private SelectableDataModel<Order> orders;

    private List<SelectItem> sellStatusItems;

    private List<SelectItem> paymentStatusItems;

    private List<SelectItem> orderStatusItems;

    public OrderAction() {
        super();
    }

    public String listOrders() throws WebException {

        verifyLogin();
        return "listOrders";
    }

    public String prepareInsertOrder() throws WebException {

        verifyLogin();
        setActionType(ActionType.INSERT);
        setOrder(null);
        return "editOrder";
    }

    public String insertOrder() throws WebException {

        verifyLogin();
        String pageReturn;
        try {
            // ORDER
            OrderBusiness.insert(getOrder());
            clearOrders();
            setOrder(null);
            pageReturn = listOrders();
        } catch (BusinessException be) {
            addBusinessException("frmOrder", be);
            pageReturn = "editOrder";
        } catch (TransactionException te) {
            throw new WebException(te);
        }
        return pageReturn;
    }

    public String prepareEditOrder() throws WebException {

        verifyLogin();
        String pageReturn = "editOrder";
        setActionType(ActionType.EDIT);
        try {
            int orderId = getOrder().getId();
            int userId = getLocalUser().getId();
            setOrder(OrderBusiness.findByPK(userId, orderId));
        } catch (BusinessException be) {
            addBusinessException("frmListOrders", be);
            pageReturn = listOrders();
        } catch (TransactionException te) {
            throw new WebException(te);
        }
        return pageReturn;
    }

    public String editOrder() throws WebException {

        verifyLogin();
        String pageReturn;
        try {
            OrderBusiness.update(order);
            clearOrders();
            setOrder(null);
            pageReturn = listOrders();
        } catch (BusinessException be) {
            addBusinessException("frmOrder", be);
            pageReturn = "editOrder";
        } catch (TransactionException te) {
            throw new WebException(te);
        }
        return pageReturn;
    }

    public void deleteOrder() throws WebException {

        verifyLogin();
        try {
            if (!isConfirmAction()) {
                throw new BusinessException("Exclusão pedido não confirmada.");
            } else {
                setConfirmAction(false);
            }
            OrderBusiness.delete(order);
            clearOrders();
            setOrder(null);
            clearAction();
        } catch (BusinessException be) {
            addBusinessException("frmListOrders", be);
        } catch (TransactionException te) {
            throw new WebException(te);
        }
    }

    public void prepareUpdateStatusOrder() throws WebException {

        verifyLogin();
        try {
            int orderId = getOrder().getId();
            int userId = getLocalUser().getId();
            setOrder(OrderBusiness.findByPK(userId, orderId));
            if (isActionArriveItem()) {
                getOrder().setArriveDate(getDate());
            } else if (isActionSellItem()) {
                getOrder().setSellDate(getDate());
            } else if (isActionPayItem()) {
                getOrder().setPaymentDate(getDate());
            }
        } catch (BusinessException be) {
            addBusinessException("frmListOrders", be);
        } catch (TransactionException te) {
            throw new WebException(te);
        }
    }

    public void updateStatusOrder() throws WebException {

        verifyLogin();
        try {
            if (isActionReceivePaymentItem()) {
                if (!isConfirmAction()) {
                    throw new BusinessException("Recebimento não confirmado.");
                } else {
                    setConfirmAction(false);
                }
            }
            OrderBusiness.updateStatus(order, getActionType());
            clearOrders();
            setOrder(null);
            clearAction();
        } catch (BusinessException be) {
            addBusinessException("frmListOrders", be);
        } catch (TransactionException te) {
            throw new WebException(te);
        }
    }

    public void clearAction() throws WebException {

        verifyLogin();
        setActionType(null);
        setOrder(null);
        setConfirmAction(false);
    }

    public List<SelectItem> getSellerItems() throws WebException {

        List<SelectItem> sellerItems = new ArrayList<SelectItem>();
        try {
            List<Seller> sellers = SellerBusiness.findAll(true);
            for (Seller seller : sellers) {
                sellerItems.add(new SelectItem(new Integer(seller.getId()), seller.getName()));
            }
        } catch (TransactionException te) {
            throw new WebException(te);
        }
        return sellerItems;
    }

    public List<SelectItem> getProductItems() throws WebException {

        List<SelectItem> productItems = new ArrayList<SelectItem>();
        try {
            List<Product> products = ProductBusiness.findAll(true);
            for (Product product : products) {
                productItems.add(new SelectItem(new Integer(product.getId()), product.getName()));
            }
        } catch (TransactionException te) {
            throw new WebException(te);
        }
        return productItems;
    }

    public List<SelectItem> getSellStatusItems() throws WebException {

        if (this.sellStatusItems == null) {
            this.sellStatusItems = new ArrayList<SelectItem>();
            List<SellStatus> sellStatusList = SellStatusBusiness.findAll();
            for (SellStatus status : sellStatusList) {
                this.sellStatusItems.add(new SelectItem(new Integer(status.getId()), status.getName()));
            }
        }
        return this.sellStatusItems;
    }

    public List<SelectItem> getPaymentStatusItems() throws WebException {

        if (this.paymentStatusItems == null) {
            this.paymentStatusItems = new ArrayList<SelectItem>();
            List<PaymentStatus> paymentStatusList = PaymentStatusBusiness.findAll();
            for (PaymentStatus status : paymentStatusList) {
                this.paymentStatusItems.add(new SelectItem(new Integer(status.getId()), status.getName()));
            }
        }
        return this.paymentStatusItems;
    }

    public List<SelectItem> getOrderStatusItems() throws WebException {

        if (this.orderStatusItems == null) {
            this.orderStatusItems = new ArrayList<SelectItem>();
            List<OrderStatus> orderStatusList = OrderStatusBusiness.findAll();
            for (OrderStatus status : orderStatusList) {
                this.orderStatusItems.add(new SelectItem(new Integer(status.getId()), status.getName()));
            }
        }
        return this.orderStatusItems;
    }

    public Order getOrder() {
        if (this.order == null) {
            this.order = new Order();
            this.order.setUser(getLocalUser());
            this.order.setOrderDate(getDate());
            this.order.setCurrencyType(CurrencyType.DOLLAR);
        }
        return order;
    }

    public OrderFilter getOrderFilter() {
        if (this.orderFilter == null) {
            this.orderFilter = new OrderFilter();
            this.orderFilter.setUser(getLocalUser());
            this.orderFilter.setOrderStatus(OrderStatus.UNDEFINED);
            this.orderFilter.setNoOrderStatus(false);
            this.orderFilter.setPaymentStatus(PaymentStatus.UNDEFINED);
            this.orderFilter.setSellStatus(SellStatus.UNDEFINED);
        }
        return this.orderFilter;
    }

    public void setOrder(Order order) {
        this.order = order;
    }

    public SelectableDataModel<Order> getOrders() throws WebException {
        if (this.orders == null) {
            try {
                int userId = getLocalUser().getId();
                if (isPendentOrders()) {
                    setOrders(new OrderDataModel(OrderBusiness.findPendentOnly(userId)));
                } else {
                    setOrders(new OrderDataModel(OrderBusiness.findByFilter(userId, getOrderFilter())));
                }
            } catch (TransactionException te) {
                throw new WebException(te);
            }
        }
        return orders;
    }

    public void setOrders(SelectableDataModel<Order> orders) {
        this.orders = orders;
    }

    public boolean isPendentOrders() {
        return pendentOrders;
    }

    public void setPendentOrders(boolean pendentOrders) {
        this.pendentOrders = pendentOrders;
    }

    public void clearOrders() {
        setOrders(null);
    }

    public boolean isActionArriveItem() {
        return getActionType().equals(ActionType.ARRIVE_ITEM);
    }

    public void setActionArriveItem(boolean actionArriveItem) {
        if (actionArriveItem) {
            setActionType(ActionType.ARRIVE_ITEM);
        }
    }

    public boolean isActionSellItem() {
        return getActionType().equals(ActionType.SELL_ITEM);
    }

    public void setActionSellItem(boolean actionSellItem) {
        if (actionSellItem) {
            setActionType(ActionType.SELL_ITEM);
        }
    }

    public boolean isActionReceivePaymentItem() {
        return getActionType().equals(ActionType.RECEIVE_PAYMENT);
    }

    public void setActionReceivePaymentItem(boolean actionReceivePaymentItem) {
        if (actionReceivePaymentItem) {
            setActionType(ActionType.RECEIVE_PAYMENT);
        }
    }

    public boolean isActionPayItem() {
        return getActionType().equals(ActionType.PAY_ITEM);
    }

    public void setActionPayItem(boolean actionPayItem) {
        if (actionPayItem) {
            setActionType(ActionType.PAY_ITEM);
        }
    }

    public Order getSelectedOrder() {
        return selectedOrder;
    }

    public void setSelectedOrder(Order selectedOrder) {
        this.selectedOrder = selectedOrder;
    }
    
    public void onRowSelect(SelectEvent event) {
        //
    }
    
    private static class OrderDataModel extends ListDataModel<Order> implements SelectableDataModel<Order> {

        public OrderDataModel(List<Order> dataModel) {
            super(dataModel);
        }

        @Override
        public Order getRowData(String key) {
            @SuppressWarnings("unchecked")
            List<Order> list = (List<Order>) getWrappedData();
            for (Order obj : list) {
                if (String.valueOf(obj.getId()).equals(Long.valueOf(key))) {
                    return obj;
                }
            }
            return null;
        }

        @Override
        public Object getRowKey(Order order) {
            return String.valueOf(order.getId());
        }

    }

}
